package com.zhongmai.yzfgrabanorder.netty_lib.netty;

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.zhongmai.yzfgrabanorder.netty_lib.bean.ChatInfo;
import com.zhongmai.yzfgrabanorder.netty_lib.bean.NettyBaseFeed;
import com.zhongmai.yzfgrabanorder.utils.Constants;
import com.zhongmai.yzfgrabanorder.utils.Utils;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * Created by 张俨 on 2017/10/9.
 */

public class NettyClient {

    private static NettyClient nettyClient = new NettyClient();

    private EventLoopGroup group;

    private NettyListener listener;

    private Channel channel;

    public static boolean isConnect = false;

    private int reconnectNum = 3;

    private long reconnectIntervalTime = 10000;
    public final static String TAG = NettyClient.class.getName();
    private final Gson gson;
    private Bootstrap bootstrap;

    public NettyClient() {
        gson = new Gson();
    }

    public static NettyClient getInstance() {
        return nettyClient;
    }

    public synchronized NettyClient connect() {
        if (!isConnect) {
            String s = Constants.Url.replaceAll("https:\\/\\/", "");
            String[] split = s.split(":");
            if (split.length > 0) {
                s = split[0];
            }
            group = new NioEventLoopGroup();
            bootstrap = new Bootstrap().group(group)
                    .option(ChannelOption.SO_KEEPALIVE, true) //长连接
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .option(ChannelOption.TCP_NODELAY, true)//无阻塞
                    //                    .remoteAddress(s,8888)
                    //option(ChannelOption.SO_TIMEOUT, SLEEP_TIME); //收发超时
                    .channel(NioSocketChannel.class)
                    .handler(new NettyClientInitializer(listener));
            try {
                Utils.parseHostGetIPAddress(s);
                // Utils.parseHostGetIPAddress("apio.ucpays.com");
                while (true) {
                    Thread.sleep(500);
                    if (!TextUtils.isEmpty(Constants.ip)) {
                        ChannelFuture future = bootstrap.connect(Constants.ip, 35233).sync();
                        // ChannelFuture future = bootstrap.connect("192.168.1.233",8080).sync();
                        // ChannelFuture future = bootstrap.connect(new InetSocketAddress(s, 35233)).syncUninterruptibly();
                        if (future != null && future.isSuccess()) {
                            channel = future.channel();
                            isConnect = true;
                            Log.d(TAG, "connect success !状态-------" + isConnect);
                        } else {
                            isConnect = false;
                            Log.d(TAG, "connect failed !状态---------" + isConnect);
                        }
                        future.channel().closeFuture().sync();
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_ERROR);
                reconnect();
            }
        }
        return this;
    }

    /**
     * 断开长连接
     */
    public void disconnect() {
        final NettyBaseFeed<ChatInfo> baseFeed = new NettyBaseFeed<>();
        baseFeed.setCmd("quit");
        baseFeed.setMessage("下线");
        final ChatInfo chatInfo = new ChatInfo();
        chatInfo.setUser(Constants.user);
        baseFeed.setData(chatInfo);
        NettyClient.getInstance().sendMessage(baseFeed, null);
        if (group != null) {
            group.shutdownGracefully();
        }
    }

    public void reconnect() {
        if (reconnectNum > 0 && !isConnect && Constants.manual_link) {
            Log.e(TAG, "reconnect: 重启");
            reconnectNum--;
            try {
                Thread.sleep(reconnectIntervalTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            disconnect();
            connect();
        } else {
            disconnect();
        }
    }

    public Channel getChannel() {
        return channel;
    }

    /**
     * 发送消息
     *
     * @param vo
     * @param futureListener
     */
    public void sendMessage(NettyBaseFeed vo, FutureListener futureListener) {
        boolean flag = channel != null && isConnect;
        final String s = gson.toJson(vo);
        if (!flag) {
            Log.e(TAG, "------尚未连接,不在发送--->" + s);
            return;
        }
        if (futureListener == null) {
            channel.writeAndFlush(s + "\n").addListener(new FutureListener() {

                @Override
                public void success() {
                    Log.e(TAG, "发送成功--->" + s);
                }

                @Override
                public void error() {
                    Log.e(TAG, "发送失败--->" + s);
                }
            });
        } else {
            channel.writeAndFlush(s).addListener(futureListener);
        }
    }

    /**
     * 设置重连次数
     *
     * @param reconnectNum 重连次数
     */
    public void setReconnectNum(int reconnectNum) {
        this.reconnectNum = reconnectNum;
    }

    /**
     * 设置重连时间间隔
     *
     * @param reconnectIntervalTime 时间间隔
     */
    public void setReconnectIntervalTime(long reconnectIntervalTime) {
        this.reconnectIntervalTime = reconnectIntervalTime;
    }

    public boolean getConnectStatus() {
        return isConnect;
    }

    /**
     * 设置连接状态
     *
     * @param status
     */
    public void setConnectStatus(boolean status) {
        Log.e(TAG, "改变状态-------" + status);
        this.isConnect = status;
    }

    public void setListener(NettyListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener == null ");
        }
        this.listener = listener;
    }


}
